package com.atjg.autocat.sql;


import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

import androidx.annotation.Nullable;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public abstract class MyDaoHelper extends SQLiteOpenHelper {
    public MyDaoHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version, @Nullable DatabaseErrorHandler errorHandler) {
        super(context, name, factory, version, errorHandler);
    }

    public void onCreate(SQLiteDatabase db) {
        Class[] classes = this.classes();
        Class[] var3 = classes;
        int var4 = classes.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            Class clz = var3[var5];
            String table_name = this.tabName(clz);
            Field[] declaredFields = clz.getDeclaredFields();
            String columnsSql = "";
            if (declaredFields.length > 0) {
                Field[] var10 = declaredFields;
                int var11 = declaredFields.length;

                for(int var12 = 0; var12 < var11; ++var12) {
                    Field field = var10[var12];
                    COLUMN column = (COLUMN)field.getAnnotation(COLUMN.class);
                    if (column != null) {
                        columnsSql = columnsSql + column.name() + " " + column.type().getName();
                        if (column.primaryKey()) {
                            columnsSql = columnsSql + " primary key";
                        }

                        columnsSql = columnsSql + ",";
                    }
                }
            }

            if (!columnsSql.isEmpty()) {
                columnsSql = columnsSql.substring(0, columnsSql.length() - 1);
            }

            String sql = "create table " + table_name + "(" + columnsSql + ") ";
            Log.d("sql", sql);
            db.execSQL(sql);
        }

    }

    private String tabName(Class clz) {
        Annotation[] as = clz.getAnnotations();
        Log.d("onCreateTABLE", Arrays.toString(as));
        TABLE table = null;
        Annotation[] var4 = as;
        int var5 = as.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            Annotation an = var4[var6];
            if (an instanceof TABLE) {
                table = (TABLE)an;
                break;
            }
        }

        String table_name = table.name();
        return table_name;
    }

    protected abstract Class[] classes();

    public static void main(String[] args) {
    }

    public <T> SqlExecutor.SqlRunnable<List<T>> queryRunnable(final Class<T> clz) {
        return new SqlExecutor.SqlRunnable<List<T>>() {
            public List<T> run() {
                try {
                    return MyDaoHelper.this.query(clz);
                } catch (Exception var2) {
                    Exception e = var2;
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
            }
        };
    }

    public <T> List<T> query(Class<T> clz) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        return this.query(clz, (List)null);
    }

    public <T> List<T> query(Class<T> clz, List<Integer> id) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        return this.query(clz, id, "id");
    }

    public <T> List<T> query(Class<T> clz, List<Integer> ids, String idColumnName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Object list;
        if (ids != null) {
            list = new ArrayList();
            Iterator var5 = ids.iterator();

            while(var5.hasNext()) {
                Integer id = (Integer)var5.next();
                List<T> res = this.query(clz, id, idColumnName);
                ((List)list).addAll(res);
            }
        } else {
            list = this.query(clz, -1, idColumnName);
        }

        return (List)list;
    }

    public <T> List<T> query(Class<T> clz, int id, String idColumnName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        String tabName = this.tabName(clz);
        String sql = "select * from " + tabName;
        String[] args = null;
        if (id > 0) {
            sql = sql + " where " + idColumnName + "=?";
            args = new String[]{id + ""};
        }

        Cursor cu = this.getReadableDatabase().rawQuery(sql, args);
        List<T> list = new ArrayList();

        while(cu.moveToNext()) {
            T t = clz.getConstructor().newInstance();
            Field[] declaredFields = clz.getDeclaredFields();
            Field[] var11 = declaredFields;
            int var12 = declaredFields.length;

            for(int var13 = 0; var13 < var12; ++var13) {
                Field f = var11[var13];
                COLUMN column = (COLUMN)f.getAnnotation(COLUMN.class);
                if (column != null) {
                    f.setAccessible(true);
                    int columnIndex = cu.getColumnIndex(column.name());
                    if (columnIndex >= 0) {
                        switch (column.type()) {
                            case INTEGER:
                                f.set(t, cu.getInt(columnIndex));
                                break;
                            case TEXT:
                                f.set(t, cu.getString(columnIndex));
                                break;
                            case BOOLEAN:
                                f.set(t, cu.getInt(columnIndex) == 1);
                                break;
                            case REAL:
                                f.set(t, cu.getDouble(columnIndex));
                        }
                    }
                }
            }

            list.add(t);
        }

        cu.close();
        return list;
    }

    public <T> List<T> queryData(Class<T> clz, String phoneNum, String idColumnName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        String tabName = this.tabName(clz);
        String sql = "select * from " + tabName;
        String[] args = null;
        sql = sql + " where " + idColumnName + "=?";
        args = new String[]{phoneNum + ""};
        Cursor cu = this.getReadableDatabase().rawQuery(sql, args);
        List<T> list = new ArrayList();

        while(cu.moveToNext()) {
            T t = clz.getConstructor().newInstance();
            Field[] declaredFields = clz.getDeclaredFields();
            Field[] var11 = declaredFields;
            int var12 = declaredFields.length;

            for(int var13 = 0; var13 < var12; ++var13) {
                Field f = var11[var13];
                COLUMN column = (COLUMN)f.getAnnotation(COLUMN.class);
                if (column != null) {
                    f.setAccessible(true);
                    int columnIndex = cu.getColumnIndex(column.name());
                    if (columnIndex >= 0) {
                        switch (column.type()) {
                            case INTEGER:
                                f.set(t, cu.getInt(columnIndex));
                                break;
                            case TEXT:
                                f.set(t, cu.getString(columnIndex));
                                break;
                            case BOOLEAN:
                                f.set(t, cu.getInt(columnIndex) == 1);
                                break;
                            case REAL:
                                f.set(t, cu.getDouble(columnIndex));
                        }
                    }
                }
            }

            list.add(t);
        }

        cu.close();
        return list;
    }

    public <T> long insert(T t) throws IllegalAccessException {
        String tabName = this.tabName(t.getClass());
        Field[] declaredFields = t.getClass().getDeclaredFields();
        ContentValues key_values = new ContentValues();
        Field[] var5 = declaredFields;
        int var6 = declaredFields.length;

        for(int var7 = 0; var7 < var6; ++var7) {
            Field f = var5[var7];
            COLUMN column = (COLUMN)f.getAnnotation(COLUMN.class);
            if (column != null) {
                f.setAccessible(true);
                String columnN = column.name();
                Object v = f.get(t);
                switch (column.type()) {
                    case INTEGER:
                        key_values.put(columnN, (Integer)v);
                        break;
                    case TEXT:
                        key_values.put(columnN, (String)v);
                        break;
                    case BOOLEAN:
                        key_values.put(columnN, (Boolean)v);
                        break;
                    case REAL:
                        key_values.put(columnN, (Double)v);
                }
            }
        }

        try {
            return this.getWritableDatabase().insert(tabName, (String)null, key_values);
        } catch (Exception var12) {
            return 0L;
        }
    }

    public <T> void insert(List<T> ts) throws IllegalAccessException {
        Iterator var2 = ts.iterator();

        long resId;
        do {
            if (!var2.hasNext()) {
                return;
            }

            T t = (T) var2.next();
            resId = this.insert(t);
        } while(resId != -1L);

        throw new IllegalAccessException("insert error");
    }

    public int delete(Class tabClz, int id) {
        String tabName = this.tabName(tabClz);
        String wh = id <= 0 ? null : "id=?";
        String[] args = id <= 0 ? null : new String[]{id + ""};
        return this.getWritableDatabase().delete(tabName, wh, args);
    }

    public <T> int delete(T t) throws IllegalAccessException {
        Class clz = t.getClass();
        Field[] var3 = clz.getDeclaredFields();
        int var4 = var3.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            Field field = var3[var5];
            COLUMN column = (COLUMN)field.getAnnotation(COLUMN.class);
            if (column != null && column.name().equals("id")) {
                field.setAccessible(true);
                int id = (Integer)field.get(t);
                return this.delete(clz, id);
            }
        }

        return -1;
    }

    public <T> int update(T t) throws IllegalAccessException {
        Class clz = t.getClass();
        String tabName = this.tabName(clz);
        int id = 0;
        ContentValues vs = new ContentValues();
        Field[] var6 = clz.getDeclaredFields();
        int var7 = var6.length;

        for(int var8 = 0; var8 < var7; ++var8) {
            Field field = var6[var8];
            COLUMN column = (COLUMN)field.getAnnotation(COLUMN.class);
            if (column != null) {
                field.setAccessible(true);
                Object v = field.get(t);
                if (column.name().equals("id")) {
                    id = (Integer)v;
                } else {
                    switch (column.type()) {
                        case INTEGER:
                            vs.put(column.name(), (Integer)v);
                            break;
                        case TEXT:
                            vs.put(column.name(), (String)v);
                            break;
                        case BOOLEAN:
                            vs.put(column.name(), (Boolean)v);
                            break;
                        case REAL:
                            vs.put(column.name(), (Double)v);
                    }
                }
            }
        }

        return this.getWritableDatabase().update(tabName, vs, "id=?", new String[]{id + ""});
    }

    public void deleteAll(Class latLngCClass) {
        this.delete(latLngCClass, -1);
    }

    public <T> List<T> queryJoin(Class clz, List<Integer> id) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, InstantiationException {
        List<T> beans = this.query(clz, id);
        List<Field> foreignBeans = new ArrayList();
        Field[] declaredFields = clz.getDeclaredFields();
        Field[] var6 = declaredFields;
        int var7 = declaredFields.length;

        Field f;
        ForeignBean foreignBean;
        for(int var8 = 0; var8 < var7; ++var8) {
            f = var6[var8];
            foreignBean = (ForeignBean)f.getAnnotation(ForeignBean.class);
            if (foreignBean != null) {
                foreignBeans.add(f);
            }
        }

        Iterator var22 = beans.iterator();

        while(true) {
            Object bean;
            do {
                if (!var22.hasNext()) {
                    return beans;
                }

                bean = var22.next();
            } while(foreignBeans.isEmpty());

            Iterator var24 = foreignBeans.iterator();

            while(var24.hasNext()) {
                f = (Field)var24.next();
                foreignBean = (ForeignBean)f.getAnnotation(ForeignBean.class);
                Class mapClz = foreignBean.map();
                String foreign_key = foreignBean.foreign_key();
                String primary_key = foreignBean.primary_key();
                Class beanClz = foreignBean.bean();
                Field fieldId = this.columnFind(clz, "id");
                if (fieldId == null) {
                    throw new IllegalAccessException("not find foreignBean id");
                }

                fieldId.setAccessible(true);
                Object id_primary_key = fieldId.get(bean);
                List foreign_keys = this.query(mapClz, (Integer)id_primary_key, primary_key);
                List<Integer> id_foreign_keys = new ArrayList();
                Iterator var19 = foreign_keys.iterator();

                while(var19.hasNext()) {
                    Object foreign_keyBean = var19.next();
                    Field foreign_keyField = this.columnFind(mapClz, foreign_key);
                    foreign_keyField.setAccessible(true);
                    id_foreign_keys.add((Integer)foreign_keyField.get(foreign_keyBean));
                }

                Log.d("DaoHelper foreign_keys", Arrays.toString(foreign_keys.toArray()));
                List<Object> res = this.queryJoin(beanClz, id_foreign_keys);
                Log.d("DaoHelper queryJoin", Arrays.toString(res.toArray()));
                f.set(bean, res);
            }
        }
    }

    public <T> List<T> queryJoin(Class clz) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, InstantiationException {
        return this.queryJoin(clz, (List)null);
    }

    public <T> SqlExecutor.SqlRunnable<List<T>> queryJoinRunnable(final Class clz) {
        return new SqlExecutor.SqlRunnable<List<T>>() {
            public List<T> run() {
                try {
                    return MyDaoHelper.this.queryJoin(clz);
                } catch (Exception var2) {
                    Exception e = var2;
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
            }
        };
    }

    private Field columnFind(Class clz, String columnId) {
        Field[] declaredFields = clz.getDeclaredFields();
        Field[] var4 = declaredFields;
        int var5 = declaredFields.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            Field f = var4[var6];
            COLUMN column = (COLUMN)f.getAnnotation(COLUMN.class);
            if (column != null && column.name().equals(columnId)) {
                return f;
            }
        }

        return null;
    }
}
